home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / monmove.c < prev    next >
C/C++ Source or Header  |  1993-01-22  |  31KB  |  1,085 lines

  1. /*    SCCS Id: @(#)monmove.c    3.1    92/12/06    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "mfndpos.h"
  7. #include "artifact.h"
  8.  
  9. #ifdef OVL0
  10.  
  11. static int FDECL(disturb,(struct monst *));
  12. static void FDECL(distfleeck,(struct monst *,int *,int *,int *));
  13.  
  14. #endif /* OVL0 */
  15. #ifdef OVL1
  16.  
  17. STATIC_OVL boolean FDECL(mdig_tunnel,(struct monst *));
  18.  
  19. #endif /* OVL1 */
  20. #ifdef OVLB
  21.  
  22. boolean /* TRUE : mtmp died */
  23. mb_trapped(mtmp)
  24. register struct monst *mtmp;
  25. {
  26.     if (flags.verbose) {
  27.         if (cansee(mtmp->mx, mtmp->my))
  28.            pline("KABOOM!!  You see a door explode.");
  29.         else if (flags.soundok)
  30.                You("hear a distant explosion.");
  31.     }
  32.     mtmp->mstun = 1;
  33.     mtmp->mhp -= rnd(15);
  34.     if(mtmp->mhp <= 0) {
  35.         mondied(mtmp);
  36.         return(TRUE);
  37.     }
  38.     return(FALSE);
  39. }
  40.  
  41. #endif /* OVLB */
  42. #ifdef OVL1
  43.  
  44. /* Return TRUE if monster died, FALSE otherwise. */
  45. STATIC_OVL boolean
  46. mdig_tunnel(mtmp)
  47. register struct monst *mtmp;
  48. {
  49.     register struct rm *here;
  50.     register int pile;
  51.  
  52.     here = &levl[mtmp->mx][mtmp->my];
  53.     if (here->typ == SDOOR) here->typ = DOOR;
  54.  
  55.     /* Eats away door if present & closed or locked */
  56.     if(closed_door(mtmp->mx, mtmp->my)) {
  57.         if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
  58.         add_damage(mtmp->mx, mtmp->my, 0L);
  59.         unblock_point(mtmp->mx,mtmp->my);    /* vision */
  60.         if(here->doormask & D_TRAPPED) {
  61.         here->doormask = D_NODOOR;
  62.         if(mb_trapped(mtmp)) {    /* mtmp is killed */
  63.             newsym(mtmp->mx,mtmp->my);
  64.             return TRUE;
  65.         }
  66.         } else {
  67.         if(!rn2(3) && flags.verbose)    /* not too often.. */
  68.             You("feel an unexpected draft of air.");
  69.         here->doormask = D_BROKEN;
  70.         }
  71.         newsym(mtmp->mx,mtmp->my);
  72.         return FALSE;
  73.     } else
  74.     if (!IS_ROCK(here->typ)) /* no dig */
  75.         return(FALSE);
  76.  
  77.     /* Only rock and walls fall through to this point. */
  78.     if ((here->diggable & W_NONDIGGABLE)) {
  79.         impossible("mdig_tunnel:  %s at (%d,%d) is undiggable",
  80.                (IS_WALL(here->typ) ? "wall" : "stone"),
  81.                (int) mtmp->mx, (int) mtmp->my);
  82.         return FALSE;    /* still alive */
  83.     }
  84.  
  85.     if(IS_WALL(here->typ)) {
  86.         if(flags.soundok && flags.verbose && !rn2(5))
  87.         You("hear the sound of crashing rock.");
  88.         if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
  89.             add_damage(mtmp->mx, mtmp->my, 0L);
  90.         if (level.flags.is_maze_lev) {
  91.         here->typ = ROOM;
  92.         } else if (level.flags.is_cavernous_lev) {
  93.         here->typ = CORR;
  94.         } else {
  95.         here->typ = DOOR;
  96.         here->doormask = D_NODOOR;
  97.         }
  98.     } else    
  99.         here->typ = CORR;
  100.  
  101.     pile = rnd(12);
  102.     if(pile < 5)    /* leave behind some rocks? */
  103.         (void) mksobj_at((pile == 1)? BOULDER : ROCK, 
  104.                  mtmp->mx, mtmp->my, TRUE);
  105.     newsym(mtmp->mx,mtmp->my);
  106.     if(sobj_at(BOULDER, mtmp->mx, mtmp->my) == (struct obj *)0)
  107.         unblock_point(mtmp->mx,mtmp->my);    /* vision */
  108.     return FALSE ;
  109. }
  110.  
  111. int
  112. dochugw(mtmp)
  113.     register struct monst *mtmp;
  114. {
  115.     register int x = mtmp->mx;
  116.     register int y = mtmp->my;
  117.     register int rd = dochug(mtmp);
  118.     register int dd;
  119.  
  120.     if(Warning && !rd && !mtmp->mpeaceful &&
  121.             (dd = distu(mtmp->mx,mtmp->my)) < distu(x,y) &&
  122.             dd < 100 && !canseemon(mtmp)) {
  123.         /* Note: this assumes we only want to warn against the monster to
  124.          * which the weapon does extra damage, as there is no "monster
  125.          * which the weapon warns against" field.
  126.          */
  127.         if(spec_ability(uwep,SPFX_WARN) && spec_dbon(uwep,mtmp->data,1))
  128.         warnlevel = 100;
  129.         else if ((int) (mtmp->m_lev / 4) > warnlevel)
  130.         warnlevel = (mtmp->m_lev / 4);
  131.     }
  132.     /* check whether hero notices monster and stops current activity */
  133.     if (occupation && !rd && !Confusion &&
  134.         (!mtmp->mpeaceful || Hallucination) &&
  135.         canseemon(mtmp) && !cansee(x,y) &&
  136.         distu(mtmp->mx,mtmp->my) <= (BOLT_LIM+1)*(BOLT_LIM+1))
  137.         stop_occupation();
  138.  
  139.     return(rd);
  140. }
  141.  
  142. #endif /* OVL1 */
  143. #ifdef OVL2
  144.  
  145. boolean
  146. onscary(x, y, mtmp)
  147. int x, y;
  148. struct monst *mtmp;
  149. {
  150.     if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
  151.             is_lminion(mtmp->data) || is_rider(mtmp->data) ||
  152.             mtmp->data->mlet == S_HUMAN || mtmp->mpeaceful ||
  153.             mtmp->data == &mons[PM_MINOTAUR])
  154.         return(FALSE);
  155.     return(
  156. #ifdef ELBERETH
  157.            sengr_at("Elbereth", x, y) ||
  158. #endif
  159.             sobj_at(SCR_SCARE_MONSTER, x, y) != (struct obj *)0);
  160. }
  161.  
  162. #endif /* OVL2 */
  163. #ifdef OVL0
  164.  
  165. /*
  166.  * Possibly awaken the given monster.  Return a 1 if the monster has been
  167.  * jolted awake.
  168.  */
  169. static int
  170. disturb(mtmp)
  171.     register struct monst *mtmp;
  172. {
  173.     /*
  174.      * + Ettins are hard to surprise.
  175.      * + Nymphs, jabberwocks, and leprechauns do not easily wake up.
  176.      *
  177.      * Wake up if:
  178.      *    in direct LOS                        AND
  179.      *    within 10 squares                    AND
  180.      *    not stealthy or (mon is an ettin and 9/10)        AND
  181.      *    (mon is not a nymph, jabberwock, or leprechaun) or 1/50    AND
  182.      *    Aggravate or mon is (dog or human) or
  183.      *        (1/7 and mon is not mimicing furniture or object)
  184.      */
  185.     if(couldsee(mtmp->mx,mtmp->my) &&
  186.         distu(mtmp->mx,mtmp->my) <= 100 &&
  187.         (!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10))) &&
  188.         (!(mtmp->data->mlet == S_NYMPH
  189.             || mtmp->data == &mons[PM_JABBERWOCK]
  190.             || mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50)) &&
  191.         (Aggravate_monster
  192.             || (mtmp->data->mlet == S_DOG ||
  193.                 mtmp->data->mlet == S_HUMAN)
  194.             || (!rn2(7) && mtmp->m_ap_type != M_AP_FURNITURE &&
  195.                 mtmp->m_ap_type != M_AP_OBJECT) )) {
  196.  
  197.         mtmp->msleep = 0;
  198.         return(1);
  199.     }
  200.     return(0);
  201. }
  202.  
  203. static void
  204. distfleeck(mtmp,inrange,nearby,scared)
  205. register struct monst *mtmp;
  206. int *inrange, *nearby, *scared;
  207. {
  208.     int seescaryx, seescaryy;
  209.  
  210.     *inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
  211.                             (BOLT_LIM * BOLT_LIM));
  212.     *nearby = *inrange && monnear(mtmp, mtmp->mux, mtmp->muy);
  213.  
  214.     /* Note: if your image is displaced, the monster sees the Elbereth
  215.      * at your displaced position, thus never attacking your displaced
  216.      * position, but possibly attacking you by accident.  If you are
  217.      * invisible, it sees the Elbereth at your real position, thus never
  218.      * running into you by accident but possibly attacking the spot
  219.      * where it guesses you are.
  220.      */
  221.     if (Invis && !perceives(mtmp->data)) {
  222.         seescaryx = mtmp->mux;
  223.         seescaryy = mtmp->muy;
  224.     } else {
  225.         seescaryx = u.ux;
  226.         seescaryy = u.uy;
  227.     }
  228.     *scared = (*nearby && (onscary(seescaryx, seescaryy, mtmp) ||
  229.                    (!mtmp->mpeaceful &&
  230.                     in_your_sanctuary(mtmp->mx, mtmp->my))));
  231.  
  232.     if(*scared && !mtmp->mflee) {
  233. #ifdef POLYSELF
  234.         if (!sticks(uasmon))
  235. #endif
  236.             unstuck(mtmp);    /* monster lets go when fleeing */
  237.         mtmp->mflee = 1;
  238. #ifdef STUPID
  239.         if (rn2(7))
  240.             mtmp->mfleetim = rnd(10);
  241.         else
  242.             mtmp->mfleetim = rnd(100);
  243. #else
  244.         mtmp->mfleetim = rnd(rn2(7) ? 10 : 100);
  245. #endif
  246.     }
  247.  
  248. }
  249.  
  250. /* returns 1 if monster died moving, 0 otherwise */
  251. /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
  252.  * code. --KAA
  253.  */
  254. int
  255. dochug(mtmp)
  256. register struct monst *mtmp;
  257. {
  258.     register struct permonst *mdat = mtmp->data;
  259.     register int tmp=0;
  260.     int inrange, nearby, scared;
  261.  
  262. /*    Pre-movement adjustments    */
  263.  
  264.     if(mtmp->cham && !rn2(6))    /* polymorph chameleons */
  265.         (void) newcham(mtmp, (struct permonst *)0);
  266.  
  267.     /* regenerate monsters */
  268.     if (mtmp->mhp < mtmp->mhpmax && (!(moves%20) || regenerates(mdat)))
  269.         mtmp->mhp++;
  270.     if(mtmp->mspec_used) mtmp->mspec_used--;
  271.  
  272.     /* polymorph lycanthropes */
  273.     were_change(mtmp);
  274.  
  275.     /* check for waitmask status change */
  276.     if((mtmp->data->mflags3 & M3_WAITFORU) &&
  277.        (m_canseeu(mtmp) || mtmp->mhp < mtmp->mhpmax))
  278.         mtmp->data->mflags3 &= ~M3_WAITFORU;
  279.  
  280. #ifdef MULDGN
  281.     /* update quest status flags */
  282.     quest_stat_check(mtmp);
  283. #endif
  284.  
  285.     if(!mtmp->mcanmove || (mtmp->data->mflags3 & M3_WAITMASK)) {
  286.         if (Hallucination) newsym(mtmp->mx,mtmp->my);
  287. #ifdef MULDGN
  288.         if(mtmp->mcanmove && (mtmp->data->mflags3 & M3_CLOSE) &&
  289.            !mtmp->msleep && monnear(mtmp, u.ux, u.uy))
  290.         quest_talk(mtmp);    /* give the leaders a chance to speak */
  291. #endif
  292.         return(0);    /* other frozen monsters can't do anything */
  293.     }
  294.  
  295.     /* there is a chance we will wake it */
  296.     if(mtmp->msleep && !disturb(mtmp)) {
  297.         if (Hallucination) newsym(mtmp->mx,mtmp->my);
  298.         return(0);
  299.     }
  300.  
  301.     /* not frozen or sleeping: wipe out texts written in the dust */
  302.     wipe_engr_at(mtmp->mx, mtmp->my, 1);
  303.  
  304.     /* confused monsters get unconfused with small probability */
  305.     if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
  306.  
  307.     /* stunned monsters get un-stunned with larger probability */
  308.     if(mtmp->mstun && !rn2(10)) mtmp->mstun = 0;
  309.  
  310.     /* some monsters teleport */
  311.     if(mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) {
  312.         rloc(mtmp);
  313.         return(0);
  314.     }
  315.     if(mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
  316.         m_respond(mtmp);
  317.     if(mdat->mmove < rnd(6)) return(0);
  318.  
  319.     /* fleeing monsters might regain courage */
  320.     if(mtmp->mflee && !mtmp->mfleetim
  321.        && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0;
  322.  
  323.     set_apparxy(mtmp);
  324.     /* Must be done after you move and before the monster does.  The
  325.      * set_apparxy() call in m_move() doesn't suffice since the variables
  326.      * inrange, etc. all depend on stuff set by set_apparxy().
  327.      */
  328.  
  329.     /* Monsters that want to acquire things */
  330.     /* may teleport, so do it before inrange is set */
  331.     if(is_covetous(mtmp->data)) (void) tactics(mtmp);
  332.  
  333.     /* check distance and scariness of attacks */
  334.     distfleeck(mtmp,&inrange,&nearby,&scared);
  335.  
  336. #ifdef MUSE
  337.     if(find_defensive(mtmp)) {
  338.         if (use_defensive(mtmp) != 0)
  339.             return 1;
  340.     } else if(find_misc(mtmp)) {
  341.         if (use_misc(mtmp) != 0)
  342.             return 1;
  343.     }
  344. #endif
  345.  
  346.     /* Demonic Blackmail! */
  347.     if(nearby && mdat->msound == MS_BRIBE &&
  348.        mtmp->mpeaceful && !mtmp->mtame) {
  349.         if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
  350.             pline("%s whispers something to thin air.",
  351.                 cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
  352. #ifdef POLYSELF
  353.             if (is_demon(uasmon)) rloc(mtmp);
  354.               /* "Good hunting, brother" */
  355.             else {
  356. #endif
  357.                 mtmp->minvis = 0;
  358.                 /* Why?  For the same reason in real demon talk */
  359.                 pline("%s gets angry.", Amonnam(mtmp));
  360.                 mtmp->mpeaceful = 0;
  361.                 /* since no way is an image going to pay it off */
  362. #ifdef POLYSELF
  363.             }
  364. #endif
  365.         } else if(demon_talk(mtmp)) return(1);    /* you paid it off */
  366.     }
  367.  
  368.     if (mdat == &mons[PM_MIND_FLAYER] && !rn2(20)) {
  369.         struct monst *m2, *nmon = (struct monst *)0;
  370.  
  371.         if (canseemon(mtmp))
  372.             pline("%s concentrates.", Monnam(mtmp));
  373.         if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) {
  374.             You("sense a faint wave of psychic energy.");
  375.             goto toofar;
  376.         }
  377.         You("sense a wave of psychic energy pouring over you!");
  378.         if (mtmp->mpeaceful &&
  379.             (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
  380.             pline("It seems quite soothing.");
  381.         else {
  382.             register boolean m_sen = sensemon(mtmp);
  383.  
  384.             if (m_sen || (Telepat && rn2(2)) || !rn2(10)) {
  385.                 int dmg;
  386.                 pline("It locks in on your %s!",
  387.                     m_sen ? "telepathy" :
  388.                     Telepat ? "latent telepathy" : "mind");
  389.                 dmg = rnd(15);
  390.                 if (Half_spell_damage) dmg = (dmg+1) / 2;
  391.                 losehp(dmg, "psychic blast", KILLED_BY_AN);
  392.             }
  393.         }
  394.         for(m2=fmon; m2; m2 = nmon) {
  395.             nmon = m2->nmon;
  396.             if (m2->mpeaceful != mtmp->mpeaceful) continue;
  397.             if (mindless(m2->data)) continue;
  398.             if (m2 == mtmp) continue;
  399.             if ((telepathic(m2->data) &&
  400.                 (rn2(2) || m2->mblinded)) || !rn2(10)) {
  401.                 if (cansee(m2->mx, m2->my))
  402.                     pline("It locks in on %s.", mon_nam(m2));
  403.                 m2->mhp -= rnd(15);
  404.                 if (m2->mhp <= 0)
  405.                     monkilled(m2, "", AD_DRIN);
  406.             }
  407.         }
  408.     }
  409. toofar:
  410. #ifdef MUSE
  411.     /* If monster is nearby you, and has to wield a weapon, do so.   This
  412.      * costs the monster a move, of course.
  413.      */
  414.     if((!mtmp->mpeaceful || Conflict) && inrange &&
  415.        dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8
  416.        && attacktype(mdat, AT_WEAP)) {
  417.         if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
  418.         mtmp->weapon_check = NEED_HTH_WEAPON;
  419.         if (mon_wield_item(mtmp) != 0) return(0);
  420.         }
  421.     }
  422. #endif
  423. /*    Now the actual movement phase    */
  424.  
  425.     if(!nearby || mtmp->mflee || scared ||
  426.        mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
  427.        (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
  428.        (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||
  429.        (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
  430.  
  431.         tmp = m_move(mtmp, 0);
  432.         distfleeck(mtmp,&inrange,&nearby,&scared);    /* recalc */
  433.  
  434.         switch (tmp) {
  435.  
  436.             case 0:    /* no movement, but it can still attack you */
  437.             case 3:    /* absolutely no movement */
  438.                 /* for pets, case 0 and 3 are equivalent */
  439.              /* During hallucination, monster appearance should
  440.               * still change - even if it doesn't move.
  441.                */
  442.              if(Hallucination) newsym(mtmp->mx,mtmp->my);
  443.              break;
  444.              case 1:    /* monster moved */
  445.             /* Maybe it stepped on a trap and fell asleep... */
  446.             if(mtmp->msleep || !mtmp->mcanmove) return(0);
  447.              if(!nearby && ranged_attk(mdat)) break;
  448.              else if(mdat->mmove <= 12) {
  449.                 /* a monster that's digesting you can move at the
  450.                  * same time -dlc
  451.                  */
  452.                 if(u.uswallow && mtmp == u.ustuck)
  453.                 return(mattacku(mtmp));
  454.                 return(0);
  455.             }
  456.              break;
  457.              case 2:    /* monster died */
  458.              return(1);
  459.          }
  460.     }
  461.  
  462. /*    Now, attack the player if possible - one attack set per monst    */
  463.  
  464.     if (!mtmp->mpeaceful ||
  465.         (Conflict && !resist(mtmp, RING_CLASS, 0, 0))) {
  466.         if(inrange && !noattacks(mdat) && u.uhp > 0 && !scared && tmp != 3)
  467.         if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
  468.  
  469.         if(mtmp->wormno) wormhitu(mtmp);
  470.     }
  471. #ifdef MULDGN
  472.     /* special speeches for quest monsters */
  473.     if(!mtmp->msleep && mtmp->mcanmove && nearby)
  474.         quest_talk(mtmp);
  475.     else
  476. #endif
  477.         /* extra emotional attack for vile monsters */
  478.         if(inrange && mtmp->data->msound == MS_CUSS && !mtmp->mpeaceful &&
  479.            couldsee(mtmp->mx, mtmp->my) && !mtmp->minvis && !rn2(5))
  480.         cuss(mtmp);
  481.  
  482.     /* extra movement for fast monsters */
  483.     if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1);
  484.     return(tmp == 2);
  485. }
  486.  
  487. static const char NEARDATA practical[] = { WEAPON_CLASS, ARMOR_CLASS, GEM_CLASS, FOOD_CLASS, 0 };
  488. static const char NEARDATA magical[] = {
  489.     AMULET_CLASS, POTION_CLASS, SCROLL_CLASS, WAND_CLASS, RING_CLASS,
  490.     SPBOOK_CLASS, 0 };
  491. static const char NEARDATA indigestion[] = { BALL_CLASS, ROCK_CLASS, 0 };
  492.  
  493. #ifdef POLYSELF
  494. boolean
  495. itsstuck(mtmp)
  496. register struct monst *mtmp;
  497. {
  498.     if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) {
  499.         pline("%s cannot escape from you!", Monnam(mtmp));
  500.         return(TRUE);
  501.     }
  502.     return(FALSE);
  503. }
  504. #endif
  505.  
  506. int
  507. m_move(mtmp, after)
  508. register struct monst *mtmp;
  509. register int after;
  510. {
  511.     register int appr;
  512.     xchar gx,gy,nix,niy,chcnt;
  513.     int chi;    /* could be schar except for stupid Sun-2 compiler */
  514.     boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
  515.     boolean likerock=0, can_tunnel=0;
  516.     boolean can_open=0, can_unlock=0, doorbuster=0;
  517. #ifdef MUSE
  518.     boolean uses_items=0;
  519. #endif
  520.     struct permonst *ptr;
  521.     schar mmoved = 0;    /* not strictly nec.: chi >= 0 will do */
  522.     long info[9];
  523.     long flag;
  524.     int  omx = mtmp->mx, omy = mtmp->my;
  525. #ifdef MUSE
  526.     struct obj *mw_tmp;
  527. #endif
  528.  
  529.     if(mtmp->mtrapped) {
  530.         int i = mintrap(mtmp);
  531.         if(i >= 2) { newsym(mtmp->mx,mtmp->my); return(2); }/* it died */
  532.         if(i == 1) return(0);    /* still in trap, so didn't move */
  533.     }
  534.     ptr = mtmp->data; /* mintrap() can change mtmp->data -dlc */
  535.     if(hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10))
  536.         return(0);        /* do not leave hiding place */
  537.     if(mtmp->meating) {
  538.         mtmp->meating--;
  539.         return(3);            /* still eating */
  540.     }
  541.  
  542.     set_apparxy(mtmp);
  543.     /* where does mtmp think you are? */
  544.     /* Not necessary if m_move called from this file, but necessary in
  545.      * other calls of m_move (ex. leprechauns dodging)
  546.      */
  547.     can_tunnel = tunnels(ptr) &&
  548. #ifdef REINCARNATION
  549.         !Is_rogue_level(&u.uz) &&
  550. #endif
  551. #ifdef MUSE
  552.         (!needspick(ptr) ||
  553.          (m_carrying(mtmp, PICK_AXE) &&
  554.           (mtmp->weapon_check != NO_WEAPON_WANTED ||
  555.            !(mw_tmp = MON_WEP(mtmp)) || mw_tmp->otyp == PICK_AXE)));
  556. #else
  557.         (!needspick(ptr) || m_carrying(mtmp, PICK_AXE));
  558. #endif
  559.     can_open = !(nohands(ptr) || verysmall(ptr));
  560.     can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) || mtmp->iswiz);
  561.     doorbuster = is_giant(ptr);
  562.     if(mtmp->wormno) goto not_special;
  563.     /* my dog gets special treatment */
  564.     if(mtmp->mtame) {
  565.         mmoved = dog_move(mtmp, after);
  566.         goto postmov;
  567.     }
  568.  
  569.     /* likewise for shopkeeper */
  570.     if(mtmp->isshk) {
  571.         mmoved = shk_move(mtmp);
  572.         if(mmoved == -2) return(2);
  573.         if(mmoved >= 0) goto postmov;
  574.         mmoved = 0;        /* follow player outside shop */
  575.     }
  576.  
  577.     /* and for the guard */
  578.     if(mtmp->isgd) {
  579.         mmoved = gd_move(mtmp);
  580.         if(mmoved == -2) return(2);
  581.         if(mmoved >= 0) goto postmov;
  582.         mmoved = 0;
  583.     }
  584.  
  585.     /* and the acquisitive monsters get special treatment */
  586.     if(is_covetous(ptr)) {
  587.         xchar tx = (xchar)((mtmp->mstrategy >> 16) & 0xff),
  588.           ty = (xchar)((mtmp->mstrategy >> 8) & 0xff);
  589.         struct monst *intruder = m_at(tx, ty);
  590.         /*
  591.          * if there's a monster on the object or in possesion of it,
  592.          * attack it.
  593.          */
  594.         if((dist2(mtmp->mx, mtmp->my, tx, ty) < 2) &&
  595.            intruder && (intruder != mtmp)) {
  596.  
  597.         if(mattackm(mtmp, intruder) == 2) return(2);
  598.         mmoved = 1;
  599.         } else mmoved = 0;
  600.         goto postmov;
  601.     }
  602.  
  603.     /* and for the priest */
  604.     if(mtmp->ispriest) {
  605.         mmoved = pri_move(mtmp);
  606.         if(mmoved == -2) return(2);
  607.         if(mmoved >= 0) goto postmov;
  608.         mmoved = 0;
  609.     }
  610.  
  611. #ifdef MAIL
  612.     if(ptr == &mons[PM_MAIL_DAEMON]) {
  613.         if(flags.soundok && canseemon(mtmp))
  614.         verbalize("I'm late!");
  615.         mongone(mtmp);
  616.         return(2);        
  617.     }
  618. #endif
  619.  
  620.     /* teleport if that lies in our nature */
  621.     if(ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan) {
  622.         if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
  623.         rloc(mtmp);
  624.         else
  625.         mnexto(mtmp);
  626.         mmoved = 1;
  627.         goto postmov;
  628.     }
  629. not_special:
  630.     if(u.uswallow && !mtmp->mflee && u.ustuck != mtmp) return(1);
  631.     appr = 1;
  632.     omx = mtmp->mx;
  633.     omy = mtmp->my;
  634.     gx = mtmp->mux;
  635.     gy = mtmp->muy;
  636.     if(mtmp->mflee) appr = -1;
  637.     if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck))
  638.         appr = 0;
  639.     else {
  640.         boolean should_see = (couldsee(omx, omy) &&     
  641.                           (levl[gx][gy].lit || 
  642.                        !levl[omx][omy].lit) &&
  643.                       (dist2(omx, omy, gx, gy) <= 36));
  644.  
  645.         if (!mtmp->mcansee || 
  646.                 (should_see && Invis && !perceives(ptr)) || 
  647. #ifdef POLYSELF
  648.                 (u.usym == S_MIMIC_DEF) || u.uundetected ||
  649. #endif
  650.                 (mtmp->mpeaceful && !mtmp->isshk) ||  /* allow shks to follow */
  651.                 ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT ||
  652.               ptr->mlet == S_LIGHT) && !rn2(3)))
  653.             appr = 0;  
  654.     
  655.             if(monsndx(ptr) == PM_LEPRECHAUN && (appr == 1) && 
  656.                (mtmp->mgold > u.ugold))
  657.             appr = -1;
  658.  
  659.         if (!should_see && can_track(ptr)) {
  660.             register coord *cp;
  661.  
  662.             cp = gettrack(omx,omy);
  663.             if (cp) {
  664.                     gx = cp->x;
  665.                     gy = cp->y;
  666.             }
  667.         }
  668.     }
  669.  
  670. #ifdef REINCARNATION
  671.     if (!Is_rogue_level(&u.uz))
  672. #endif
  673.     {
  674.         register int pctload = (curr_mon_load(mtmp) * 100) /
  675.             max_mon_load(mtmp);
  676.  
  677.         /* look for gold or jewels nearby */
  678.         likegold = (likes_gold(ptr) && pctload < 95);
  679.         likegems = (likes_gems(ptr) && pctload < 85);
  680. #ifdef MUSE
  681.         uses_items = (!mindless(ptr) && !is_animal(ptr)
  682.             && pctload < 75);
  683. #endif
  684.         likeobjs = (likes_objs(ptr) && pctload < 75);
  685.         likemagic = (likes_magic(ptr) && pctload < 85);
  686.         likerock = (throws_rocks(ptr) && pctload < 50);
  687.         conceals = hides_under(ptr);
  688.     }
  689.  
  690. #define SQSRCHRADIUS    5
  691.  
  692.       { register int minr = SQSRCHRADIUS;    /* not too far away */
  693.     register struct obj *otmp;
  694.     register int xx, yy;
  695.     int oomx, oomy, lmx, lmy;
  696.  
  697.     /* cut down the search radius if it thinks character is closer. */
  698.     if(distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS &&
  699.         !mtmp->mpeaceful) minr--;
  700.     /* guards shouldn't get too distracted */
  701.     if(!mtmp->mpeaceful && is_mercenary(ptr)) minr = 1;
  702.  
  703.     if((likegold || likegems || likeobjs || likemagic || likerock || conceals)
  704.           && (!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) {
  705.     look_for_obj:
  706.         oomx = min(COLNO-1, omx+minr);
  707.         oomy = min(ROWNO-1, omy+minr);
  708.         lmx = max(1, omx-minr);
  709.         lmy = max(0, omy-minr);
  710.         for(otmp = fobj; otmp; otmp = otmp->nobj) {
  711.         xx = otmp->ox;
  712.         yy = otmp->oy;
  713.         if(xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) {
  714.             if(((likegold && otmp->otyp == GOLD_PIECE) ||
  715.                (likeobjs && index(practical, otmp->oclass)) ||
  716.                (likemagic && index(magical, otmp->oclass)) ||
  717. #ifdef MUSE
  718.                (uses_items && searches_for_item(mtmp, otmp)) ||
  719. #endif
  720.                (likerock && otmp->otyp == BOULDER) ||
  721.                (likegems && otmp->oclass == GEM_CLASS &&
  722.             objects[otmp->otyp].oc_material != MINERAL) ||
  723.                (conceals && !cansee(otmp->ox,otmp->oy)) ||
  724.                (ptr == &mons[PM_GELATINOUS_CUBE] &&
  725.             !index(indigestion, otmp->oclass) &&
  726.             !(otmp->otyp == CORPSE &&
  727.               otmp->corpsenm == PM_COCKATRICE))
  728.               ) && touch_artifact(otmp,mtmp)) {
  729.             if(can_carry(mtmp,otmp) &&
  730.                (throws_rocks(ptr) ||
  731.                 !sobj_at(BOULDER,xx,yy)) &&
  732.                (ptr->mlet != S_UNICORN ||
  733.                 objects[otmp->otyp].oc_material == GEMSTONE)) {
  734.                 minr = distmin(omx,omy,xx,yy);
  735.                 oomx = min(COLNO-1, omx+minr);
  736.                 oomy = min(ROWNO-1, omy+minr);
  737.                 lmx = max(1, omx-minr);
  738.                 lmy = max(0, omy-minr);
  739.                 gx = otmp->ox;
  740.                 gy = otmp->oy;
  741.             }
  742.             }
  743.         }
  744.         }
  745.     } else if(likegold) {
  746.         /* don't try to pick up anything else, but use the same loop */
  747. #ifdef MUSE
  748.         uses_items =
  749. #endif
  750.         likegems = likeobjs = likemagic = likerock = conceals = 0;
  751.         goto look_for_obj;
  752.     }
  753.  
  754.     if(minr < SQSRCHRADIUS && appr == -1) {
  755.         if(distmin(omx,omy,mtmp->mux,mtmp->muy) <= 3) {
  756.         gx = mtmp->mux;
  757.         gy = mtmp->muy;
  758.         } else
  759.         appr = 1;
  760.     }
  761.       }
  762.     nix = omx;
  763.     niy = omy;
  764.     flag = ALLOW_TRAPS;
  765.     if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
  766.         flag |= (ALLOW_SANCT | ALLOW_SSM);
  767.     else flag |= ALLOW_U;
  768.     if (ptr->mlet == S_UNICORN) flag |= NOTONL;
  769.     if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
  770.     if (can_tunnel) flag |= ALLOW_DIG;
  771.     if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
  772.     if (is_undead(ptr)) flag |= NOGARLIC;
  773.     if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
  774.     if (can_open) flag |= OPENDOOR;
  775.     if (can_unlock) flag |= UNLOCKDOOR;
  776.     if (doorbuster) flag |= BUSTDOOR;
  777.     {
  778.         register int i, j, nx, ny, nearer;
  779.         int jcnt, cnt;
  780.         int ndist, nidist;
  781.         register coord *mtrk;
  782.         coord poss[9];
  783.  
  784.         cnt = mfndpos(mtmp, poss, info, flag);
  785.         chcnt = 0;
  786.         jcnt = min(MTSZ, cnt-1);
  787.         chi = -1;
  788.         nidist = dist2(nix,niy,gx,gy);
  789.         /* allow monsters be shortsighted on some levels for balance */
  790.         if(!mtmp->mpeaceful && level.flags.shortsighted &&
  791.            nidist > (couldsee(nix,niy) ? 144 : 36) && appr == 1) appr = 0;
  792.  
  793.         for(i=0; i < cnt; i++) {
  794.         nx = poss[i].x;
  795.         ny = poss[i].y;
  796.  
  797.         if (appr != 0) {
  798.             mtrk = &mtmp->mtrack[0];
  799.             for(j=0; j < jcnt; mtrk++, j++)
  800.             if(nx == mtrk->x && ny == mtrk->y)
  801.                 if(rn2(4*(cnt-j)))
  802.                 goto nxti;
  803.         }
  804.  
  805.         nearer = ((ndist = dist2(nx,ny,gx,gy)) < nidist);
  806.  
  807.         if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
  808.            (!appr && !rn2(++chcnt)) || !mmoved) {
  809.             nix = nx;
  810.             niy = ny;
  811.             nidist = ndist;
  812.             chi = i;
  813.             mmoved = 1;
  814.         }
  815.         nxti:    ;
  816.         }
  817.     }
  818.  
  819.     if(mmoved) {
  820.         register int j;
  821. #ifdef POLYSELF
  822.         if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
  823.         return(3);
  824. #endif
  825. #ifdef MUSE
  826.         if (mmoved==1 && can_tunnel && needspick(ptr) &&
  827.         (!(mw_tmp = MON_WEP(mtmp)) || mw_tmp->otyp != PICK_AXE)) {
  828.         mtmp->weapon_check = NEED_PICK_AXE;
  829.         (void)mon_wield_item(mtmp);
  830.         }
  831. #endif
  832.         /* If ALLOW_U is set, either it's trying to attack you, or it
  833.          * thinks it is.  In either case, attack this spot in preference to
  834.          * all others.
  835.          */
  836.         if(info[chi] & ALLOW_U) {
  837.         nix = mtmp->mux;
  838.         niy = mtmp->muy;
  839.         }
  840.         if (nix == u.ux && niy == u.uy) {
  841.         mtmp->mux = u.ux;
  842.         mtmp->muy = u.uy;
  843.         return(0);
  844.         }
  845.         /* The monster may attack another based on 1 of 2 conditions:
  846.          * 1 - It may be confused.
  847.          * 2 - It may mistake the monster for your (displaced) image.
  848.          * Pets get taken care of above and shouldn't reach this code.
  849.          * Conflict gets handled even farther away (movemon()).
  850.          */
  851.         if((info[chi] & ALLOW_M) ||
  852.            (nix == mtmp->mux && niy == mtmp->muy)) {
  853.         struct monst *mtmp2;
  854.         int stat;
  855.         mtmp2 = m_at(nix,niy);
  856.  
  857.         stat = mattackm(mtmp, mtmp2);
  858.  
  859.         if (stat & MM_AGR_DIED)        /* aggressor died */
  860.             return 2;
  861.  
  862.         if ((stat & MM_HIT) && !(stat & MM_DEF_DIED)  &&
  863.             rn2(4) && mtmp2->mlstmv != monstermoves) {
  864.             stat = mattackm(mtmp2, mtmp);    /* return attack */
  865.             if (stat & MM_DEF_DIED)
  866.             return 2;
  867.         }
  868.         return 3;
  869.         }
  870.  
  871.         remove_monster(omx, omy);
  872.         place_monster(mtmp, nix, niy);
  873.         for(j = MTSZ-1; j > 0; j--)
  874.         mtmp->mtrack[j] = mtmp->mtrack[j-1];
  875.         mtmp->mtrack[0].x = omx;
  876.         mtmp->mtrack[0].y = omy;
  877.         /* Place a segment at the old position. */
  878.         if (mtmp->wormno) worm_move(mtmp);
  879.     } else {
  880.         if(ptr->mlet == S_UNICORN && rn2(2)) {
  881.         rloc(mtmp);
  882.         return(1);
  883.         }
  884.         if(mtmp->wormno) worm_nomove(mtmp);
  885.     }
  886. postmov:
  887.     if(mmoved == 1) {
  888.         boolean canseeit = cansee(mtmp->mx, mtmp->my);
  889.         boolean abstain = (mtmp->mpeaceful && !mtmp->mtame);
  890.  
  891.         newsym(omx,omy);        /* update the old position */
  892.         if (mintrap(mtmp) >= 2) {
  893.         if(mtmp->mx) newsym(mtmp->mx,mtmp->my);
  894.         return(2);    /* it died */
  895.         }
  896.         ptr = mtmp->data;
  897.  
  898.         /* open a door, or crash through it, if you can */
  899.         if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
  900.             && !passes_walls(ptr) /* doesn't need to open doors */
  901.             && !can_tunnel /* taken care of below */
  902.           ) {
  903.         struct rm *here = &levl[mtmp->mx][mtmp->my];
  904.         boolean btrapped = (here->doormask & D_TRAPPED);
  905.  
  906.         if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
  907.             if (flags.verbose && canseeit)
  908.             pline("%s %ss under the door.", Monnam(mtmp),
  909.                   (ptr == &mons[PM_FOG_CLOUD] ||
  910.                    ptr == &mons[PM_YELLOW_LIGHT])
  911.                   ? "flow" : "ooze");
  912.         } else if(here->doormask & D_LOCKED && can_unlock) {
  913.             if(btrapped) {
  914.             here->doormask = D_NODOOR;
  915.             newsym(mtmp->mx, mtmp->my);
  916.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  917.             if(mb_trapped(mtmp)) return(2);
  918.             } else {
  919.             if (flags.verbose) {
  920.                 if (canseeit)
  921.                   You("see a door being unlocked and opened.");
  922.                 else if (flags.soundok)
  923.                    You("hear a door being unlocked and opened.");
  924.                 }
  925.                 here->doormask = D_ISOPEN;
  926.             /* newsym(mtmp->mx, mtmp->my); */
  927.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  928.             }
  929.         } else if (here->doormask == D_CLOSED && can_open) {
  930.             if(btrapped) {
  931.             here->doormask = D_NODOOR;
  932.             newsym(mtmp->mx, mtmp->my);
  933.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  934.             if(mb_trapped(mtmp)) return(2);
  935.             } else {
  936.                 if (flags.verbose) {
  937.                 if (canseeit)
  938.                      You("see a door being opened.");
  939.                 else if (flags.soundok)
  940.                      You("hear the sound of a door opening.");
  941.                 }
  942.                 here->doormask = D_ISOPEN;
  943.             /* newsym(mtmp->mx, mtmp->my); */  /* done below */
  944.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  945.             }
  946.         } else if (here->doormask & (D_LOCKED|D_CLOSED)) {
  947.             /* mfndpos guarantees this must be a doorbuster */
  948.             if(btrapped) {
  949.             here->doormask = D_NODOOR;
  950.             newsym(mtmp->mx, mtmp->my);
  951.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  952.             if(mb_trapped(mtmp)) return(2);
  953.             } else {
  954.                 if (flags.verbose) {
  955.                 if (canseeit)
  956.                     You("see a door crash open.");
  957.                 else if (flags.soundok)
  958.                     You("hear the sound of a door crashing open.");
  959.                 }
  960.                 if (here->doormask & D_LOCKED && !rn2(2))
  961.                     here->doormask = D_NODOOR;
  962.                 else here->doormask = D_BROKEN;
  963.             /* newsym(mtmp->mx, mtmp->my); */ /* done below */
  964.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  965.             }
  966.         }
  967.         }
  968.  
  969.         /* possibly dig */
  970.         if (can_tunnel && mdig_tunnel(mtmp))
  971.             return(2);    /* mon died (position already updated) */
  972.  
  973.         /* set also in domove(), hack.c */
  974.         if (u.uswallow && mtmp == u.ustuck &&
  975.                     (mtmp->mx != omx || mtmp->my != omy)) {
  976.         /* If the monster moved, then update */
  977.         u.ux0 = u.ux;
  978.         u.uy0 = u.uy;
  979.         u.ux = mtmp->mx;
  980.         u.uy = mtmp->my;
  981.         swallowed(0);
  982.         } else
  983.         newsym(mtmp->mx,mtmp->my);
  984.  
  985.         if(OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
  986.         /* Maybe a rock mole just ate some metal object */
  987.         if(metallivorous(ptr)) meatgold(mtmp);
  988.  
  989.         if(g_at(mtmp->mx,mtmp->my) && likegold &&
  990.                     (!abstain || !rn2(10))) mpickgold(mtmp);
  991.  
  992.         /* Maybe a cube ate just about anything */
  993.         if(ptr == &mons[PM_GELATINOUS_CUBE]) meatobj(mtmp);
  994.  
  995.         if((!abstain || !rn2(10)) && 
  996.            (!*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || !rn2(25))) {
  997.             if(likeobjs) mpickstuff(mtmp, practical);
  998.             if(likemagic) mpickstuff(mtmp, magical);
  999.             if(likerock || likegems) mpickgems(mtmp);
  1000. #ifdef MUSE
  1001.             if(uses_items) mpickstuff(mtmp, (char *)0);
  1002. #endif
  1003.         }
  1004.  
  1005.         if(mtmp->minvis) {
  1006.             newsym(mtmp->mx, mtmp->my);
  1007.             if (mtmp->wormno) see_wsegs(mtmp);
  1008.         }
  1009.         }
  1010.  
  1011.         if(hides_under(ptr)) {
  1012.         mtmp->mundetected = OBJ_AT(mtmp->mx, mtmp->my);
  1013.         newsym(mtmp->mx, mtmp->my);
  1014.         }
  1015.     }
  1016.     return(mmoved);
  1017. }
  1018.  
  1019. #endif /* OVL0 */
  1020. #ifdef OVL2
  1021.  
  1022. boolean
  1023. closed_door(x, y)
  1024. register int x, y;
  1025. {
  1026.     return(IS_DOOR(levl[x][y].typ) &&
  1027.             (levl[x][y].doormask & (D_LOCKED | D_CLOSED)));
  1028. }
  1029.  
  1030. boolean
  1031. accessible(x, y)
  1032. register int x, y;
  1033. {
  1034.     return(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y));
  1035. }
  1036.  
  1037. #endif /* OVL2 */
  1038. #ifdef OVL0
  1039.  
  1040. void
  1041. set_apparxy(mtmp)        /* where does mtmp think you are standing? */
  1042.     register struct monst *mtmp;
  1043. {
  1044. #define notseen (Invis && !perceives(mtmp->data))
  1045. /*    add cases as required.  eg. Displacement ... */
  1046.     register int disp = (Underwater ? 3 : notseen ? 1 : Displaced ? 2 : 0);
  1047.  
  1048. /*     without something like the following, invis. and displ. are too */
  1049. /*    powerful. */
  1050.     register boolean gotu =
  1051.         (notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE);
  1052.  
  1053. /*    Monsters which know where you are don't suddenly forget, if you
  1054.     didn't move away. */
  1055.     if (mtmp->mux==u.ux && mtmp->muy==u.uy) gotu = 1;
  1056.  
  1057. /*     your dog follows your smell */
  1058.     if(!disp || mtmp->mtame || gotu ||
  1059. /*     Monsters touching you know where you are */
  1060.        mtmp == u.ustuck ||
  1061. /*    If invisible but not displaced, staying around gets you 'discovered' */
  1062.         (!Displaced && u.dx == 0 && u.dy == 0)) {
  1063.         mtmp->mux = u.ux;
  1064.         mtmp->muy = u.uy;
  1065.     }
  1066.     else do {
  1067.         mtmp->mux = u.ux - disp + rn2(2*disp+1);
  1068.         mtmp->muy = u.uy - disp + rn2(2*disp+1);
  1069.     } while((mtmp->mux != u.ux || mtmp->muy != u.uy) &&
  1070.             ( (!passes_walls(mtmp->data) &&
  1071.               (!ACCESSIBLE(levl[mtmp->mux][mtmp->muy].typ) ||
  1072.                (closed_door(mtmp->mux, mtmp->muy) &&
  1073.             !amorphous(mtmp->data)
  1074.                )
  1075.               )
  1076.           ) ||
  1077.           (disp==1 && mtmp->mux == mtmp->mx && mtmp->muy == mtmp->my)
  1078.             )
  1079.            );
  1080. }
  1081.  
  1082. #endif /* OVL0 */
  1083.  
  1084. /*monmove.c*/
  1085.